#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

using namespace std;
const string sep = "\r\n";

namespace protocol_ns
{
    string EnCode(const string &str)
    {
        int len = str.size();
        string ret = to_string(len);
        ret += sep;
        ret += str;
        ret += sep;
        return ret;
    }
    // "len\r\n{ }\r\n"
    string DeCode(string &str)
    {
        auto pos = str.find(sep);
        if(pos == string::npos) return string();

        string str_len = str.substr(0, pos);
        if(str_len.empty()) return string();

        int packlen = stoi(str_len);

        int total = packlen+str_len.size()+sep.size()*2;
        if(str.size() < total) return string();

        string packstr = str.substr(pos+sep.size(), packlen);
        str.erase(0, total);
        return packstr;
    }
    // {} 

    class Request
    {
    public:
        Request()
        {}
        Request(int a, int b):_a(a),_b(b)
        {}
        void Serialize(string *out)
        {
            Json::Value root;
            root["a"] = _a;
            root["b"] = _b;
            Json::FastWriter write;
            *out = write.write(root);
        }
        void UnSerialize(const string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool ret = reader.parse(in, root);
            if(!ret) exit(0);
            _a = root["a"].asInt();
            _b = root["b"].asInt();
        }
        ~Request()
        {}
        int _a;
        int _b;
    };


    class Response
    {
    public:
        Response()
        {
        }
        Response(int result):_result(result)
        {
        }
        void Serialize(string *out)
        {
            Json::Value root;
            root["result"] = _result;
            Json::FastWriter write;
            *out = write.write(root);
        }
        void UnSerialize(const string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool ret = reader.parse(in, root);
            if(!ret) exit(0);
            _result = root["result"].asInt();
        }
        ~Response()
        {}
        int _result;
    };
}